package pw.hais.utils_lib.mina.client

import android.content.ContentValues.TAG
import android.util.Log
import org.apache.mina.core.session.IdleStatus
import org.apache.mina.core.session.IoSession
import org.apache.mina.filter.codec.ProtocolCodecFilter
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory
import org.apache.mina.filter.keepalive.KeepAliveFilter
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler
import org.apache.mina.filter.logging.LoggingFilter
import org.apache.mina.transport.socket.nio.NioSocketConnector
import pw.hais.utils_lib.mina.IoHandler
import pw.hais.utils_lib.mina.OnSockectListener
import pw.hais.utils_lib.mina.SockectConfig
import pw.hais.utils_lib.utils.L
import java.net.InetSocketAddress
import java.util.concurrent.Executors


/**
 * https://github.com/cuihp/AndroidServer
 * Created by cuihp on 2017/4/15.
 */

class MinaClient(var mConfig: SockectConfig, val listener: OnSockectListener) {
    private var mConnection: NioSocketConnector? = null
    private var mSession: IoSession? = null
    private val mAddress = InetSocketAddress(mConfig.address, mConfig.port)
    private val mConnectThread = ConnectThread()
    private val mThreadPool = Executors.newFixedThreadPool(1)

    init {
        mThreadPool.execute(mConnectThread)
    }

    /**
     * 发送消息
     * @param data
     */
    fun sendMessage(data: String) {
        L.e("发送消息：$data", "Mina")
        mConnectThread.sendMsg(data)
    }

    private inner class ConnectThread : Runnable {
        override fun run() {
            mConnection = NioSocketConnector()
            mConnection!!.sessionConfig.readBufferSize = mConfig.readBufferSize
            mConnection!!.sessionConfig.setIdleTime(IdleStatus.BOTH_IDLE, 30)
            mConnection!!.filterChain.addLast("logger", LoggingFilter())
            mConnection!!.filterChain.addLast("codec", ProtocolCodecFilter(ObjectSerializationCodecFactory()))

            val kaf = KeepAliveFilter(ClientKeepAliveFactoryImpl(mConfig), IdleStatus.READER_IDLE, KeepAliveRequestTimeoutHandler.CLOSE)
            kaf.isForwardEvent = true
            kaf.requestInterval = mConfig.kafiTime      //设置当连接的读取通道空闲的时候，心跳包请求时间间隔
            kaf.requestTimeout = mConfig.kafiTime + 5   //设置心跳包请求后 等待反馈超时时间。 超过该时间后则调用KeepAliveRequestTimeoutHandler.CLOSE

            mConnection!!.filterChain.addLast("heartbeat", kaf)
            mConnection!!.connectTimeoutMillis = mConfig.outTime
            mConnection!!.handler = IoHandler(listener)
            mConnection!!.setDefaultRemoteAddress(mAddress)
            reConnect()
        }

        /**
         * 5秒重连
         */
        private fun reConnect() {
            var bool = false
            while (!bool) {
                bool = connect()
                Log.d(TAG, "是否链接:" + bool)
                try {
                    Thread.sleep(5000)
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }

            }
        }

        /**
         * 发送消息
         *
         * @param data
         */
        fun sendMsg(data: String) {
            if (mSession != null && mSession!!.isConnected) {
                mSession!!.write(data)
            }
        }

        /**
         * 链接服务器
         *
         * @return
         */
        fun connect(): Boolean {
            //停止重连
            if (mConnection == null) {
                return true
            }
            try {
                val future = mConnection!!.connect()
                future.awaitUninterruptibly()
                mSession = future.session
            } catch (e: Exception) {
                return false
            }

            return mSession != null
        }

    }

    /**
     * 断开连接
     */
    fun disConnect() {
        mConnection!!.dispose()
        mConnection = null
        mSession = null
    }
}
